package com.hbnu.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbnu.system.config.BaseException;
import com.hbnu.system.constant.RoleConstant;
import com.hbnu.system.constant.StatusCheckConstant;
import com.hbnu.system.core.base.CommonPage;
import com.hbnu.system.mapper.DeptMapper;
import com.hbnu.system.mapper.Porproject_registrationMapper;
import com.hbnu.system.model.context.BaseContext;
import com.hbnu.system.model.dto.CheckBackDTO;
import com.hbnu.system.model.dto.PorProjectTSdto;
import com.hbnu.system.model.dto.Porproject_registrationDTO;
import com.hbnu.system.model.entity.*;
import com.hbnu.system.model.query.PorProjectExportQuery;
import com.hbnu.system.model.query.PorProjectPageQuery;
import com.hbnu.system.model.vo.ExportPorProjectVO;
import java.util.UUID;
import com.hbnu.system.service.*;
import com.hbnu.system.utils.AuditUtils;
import com.hbnu.system.utils.CheckRoleUtil;
import com.hbnu.system.utils.UserInfoUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2023-05-16
 */
@Service
public class Porproject_registrationServiceImpl extends ServiceImpl<Porproject_registrationMapper, Porproject_registration> implements IPorproject_registrationService {
    @Autowired
    private IPorproject_registrationService iPorproject_registrationService;

    @Autowired
    private IUserService iUserService;


    @Autowired
    private AuditService auditService;

    @Autowired
    private IdToStatsService idToStatsService;

    @Autowired
    private PorprojectfileService porprojectfileService;

    @Autowired
    private IProjectQualificationService iProjectQualificationService;

    @Autowired
    private ZCzxfundsService zcZxfundsService;

    @Autowired
    private  DZzxfundsService dzZxfundsService;

    @Autowired
    private PorprojectauthorService porprojectauthorService;

    @Autowired
    private CheckRoleUtil checkRoleUtil;

    @Autowired
    private Validator validator;

    @Autowired
    private UserInfoUtils userInfoUtils;

    @Autowired
    private DeptMapper deptMapper;




    /**
     * 添加纵向项目
     * @param porProjectRegistrationDTO 纵向项目
     * @return  boolean
     */
    @Override
    public boolean addPorproject(Porproject_registrationDTO porProjectRegistrationDTO) {
        Porproject_registration porProjectRegistration = BeanUtil.copyProperties(porProjectRegistrationDTO, Porproject_registration.class);
        //校验参数

        porProjectRegistration.setDzFunds(0);
        porProjectRegistration.setZcFunds(0);
        porProjectRegistration.setProjectState("草稿");
        porProjectRegistration.setEnteredDate(LocalDateTime.now());
        if(porProjectRegistrationDTO.getProjectFlag() == null){
            porProjectRegistration.setProjectFlag(1);
        }

        // 将负责人的工号转化为 UID
        String account = porProjectRegistrationDTO.getAccount();
        //工号判空
        if(account == null || account.trim().isEmpty()){
            throw new BaseException("工号不能为空!");
        }
        User userByAccount = iUserService.getUserByAccount(account);
        porProjectRegistration.setHead(userByAccount.getUid());
        
        // 根据部门名称查询DeptID
        String deptName = porProjectRegistrationDTO.getUnit();
        if (deptName != null && !deptName.isEmpty()) {
            Dept dept = deptMapper.selectOne(Wrappers.lambdaQuery(Dept.class)
                    .eq(Dept::getDeptName, deptName));
            if (dept != null) {
                porProjectRegistration.setUnit(dept.getDeptID());
            } else {
                // 如果找不到对应的部门，仍然使用原值
                throw new BaseException("找不到对应的部门!");
            }
        }


        return baseMapper.insert(porProjectRegistration) == 1;
    }


    /**
     * 修改纵向项目
     * @param porProjectRegistrationDTO 纵向项目
     * @return  boolean
     */
    @Override
    public boolean updatePorproject(Porproject_registrationDTO porProjectRegistrationDTO) {
        Porproject_registration porproject_registration = BeanUtil.copyProperties(porProjectRegistrationDTO, Porproject_registration.class);

        //项目在研，项目在研待审核，项目结题待审核，项目结题状态普通不可修改项目状态
        checkRoleUtil.checkPermissionProject(porproject_registration.getProjectState());
        // 将负责人的工号转化为 UID
        String account = porProjectRegistrationDTO.getAccount();
        //工号判空
        if(account == null || account.trim().isEmpty()){
            throw new BaseException("工号不能为空!");
        }
        User userByAccount = iUserService.getUserByAccount(account);
        porproject_registration.setHead(userByAccount.getUid());

        // 根据部门名称查询DeptID
        String deptName = porProjectRegistrationDTO.getUnit();
        if (deptName != null && !deptName.isEmpty()) {
            Dept dept = deptMapper.selectOne(Wrappers.lambdaQuery(Dept.class)
                    .eq(Dept::getDeptName, deptName));
            if (dept != null) {
                porproject_registration.setUnit(dept.getDeptID());
            } else {
                // 如果找不到对应的部门，仍然使用原值
                throw new BaseException("找不到对应的部门!");
            }
        }
        return baseMapper.updateById(porproject_registration) == 1;

    }


    /**
     * 删除纵向项目
     * @param porregistrationID 纵向项目编号
     * @return  boolean
     */
    @Override
    public boolean deletePorproject(String porregistrationID) throws IOException {
        Porproject_registration porproject_registration = super.getOne(Wrappers.lambdaQuery(Porproject_registration.class)
                .eq(Porproject_registration::getPRegistrationID, porregistrationID));
        if (Objects.isNull(porproject_registration)) {
            throw new BaseException("纵向项目编号有误!");
        }
        //项目在研，项目在研待审核，项目结题待审核，项目结题状态普通不可修改项目状态
        checkRoleUtil.checkPermissionProject(porproject_registration.getProjectState());
        //删除关联的量化分数根据项目id
        iProjectQualificationService.remove(Wrappers.lambdaQuery(Project_Qualification.class)
                .eq(Project_Qualification::getProjectID, porregistrationID));

        //删除关联的作者用户
        porprojectauthorService.remove(Wrappers.lambdaQuery(Porprojectauthor.class)
                .eq(Porprojectauthor::getPregistrationid, porregistrationID));

        //删除文件
        //1.查询所有的文件根据论文id
        List<Porprojectfile> porprojectfiles = porprojectfileService.list(Wrappers.lambdaQuery(Porprojectfile.class)
              .eq(Porprojectfile::getPregistrationID, porregistrationID));
        //2.拿到文件id集合,用stream流
        List<String> fileIds = porprojectfiles.stream().map(Porprojectfile::getFileid).collect(Collectors.toList());
        for (String fileId : fileIds) {
            //3.删除文件
            porprojectfileService.deletPorprojectfile(fileId);
        }

        //删除纵向项目到账经费
        dzZxfundsService.remove(Wrappers.lambdaQuery(DZzxfunds.class)
                .eq(DZzxfunds::getPregistrationID, porregistrationID));

        //删除支出经费
        zcZxfundsService.remove(Wrappers.lambdaQuery(ZCzxfunds.class)
                .eq(ZCzxfunds::getPregistrationID, porregistrationID));

        //删除审核记录
        auditService.remove(Wrappers.lambdaQuery(Audit.class)
                .eq(Audit::getSynthesisID, porregistrationID));
        return baseMapper.deleteById(porregistrationID) == 1;
    }


    /**
     * 获取纵向项目详情——不对接前端
     * @param porprojectID 纵向项目编号
     * @return  Porproject_registration
     */
    @Override
    public Porproject_registration getPorproject(String porprojectID) {
        Porproject_registration one = super.getOne(Wrappers.lambdaQuery(Porproject_registration.class)
                .eq(Porproject_registration::getPRegistrationID, porprojectID));
        if (Objects.isNull(one)) {
            throw new BaseException("纵向项目编号异常!未查找到该纵向项目");
        }
        return one;
    }

    /**
     * 获取纵向项目详情
     * @param porprojectID
     * @return
     */
    @Override
    public Porproject_registrationDTO getPorprojectDTOById(String porprojectID) {
        Porproject_registration one = super.getOne(Wrappers.lambdaQuery(Porproject_registration.class)
                .eq(Porproject_registration::getPRegistrationID, porprojectID));
        if (Objects.isNull(one)) {
            throw new BaseException("横向项目编号异常!未查找到该横向项目");
        }
        //将录入人的id和所有作者和负责人转成姓名
        String entered = idToStatsService.IdToName(one.getEntered());
        String projectMembersName = idToStatsService.IdToAllauthor(one.getProjectMembers());

        //根据unit找到部门名称
        String unitName = null;
        if (one.getUnit() != null && !one.getUnit().isEmpty()) {
            unitName = deptMapper.getDeptNameByDeptID(one.getUnit());
        }

        //根据负责人id找到负责人的工号
        User user = iUserService.lambdaQuery().eq(User::getUid, one.getHead()).one();

        Porproject_registrationDTO onedto = new Porproject_registrationDTO();
        BeanUtils.copyProperties(one, onedto);

        onedto.setAccount(user.getAccount());
        onedto.setProjectMembersName(projectMembersName);
        onedto.setEnteredName(entered);
        // 设置部门名称，如果unit是DeptID，则转换为deptName
        if (unitName != null) {
            onedto.setUnit(unitName);
        }

        return onedto;
    }

    /**
     * 纵向在研申请
     * @param porProjectID 纵向项目编号
     * @return  true
     */
    @Override
    public Boolean CommitPorproject(String porProjectID) {
        //校验参数
        Porproject_registration porProjectRegistration = validatePorProjectRegistration(porProjectID);
        if (!porProjectRegistration.getProjectState().equals(StatusCheckConstant.DRAFT) && !porProjectRegistration.getProjectState().equals(StatusCheckConstant.PROJECT_FINISH_BACK) && !porProjectRegistration.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_BACK)) {
            throw new BaseException("该纵向项目不适用于该阶段!");
        }

        // 检查量化分数是否填写
        Project_Qualification qualification = iProjectQualificationService.getOne(
                Wrappers.lambdaQuery(Project_Qualification.class)
                        .eq(Project_Qualification::getProjectID, porProjectID)
        );
        if (Objects.isNull(qualification)) {
            throw new BaseException("请先填写纵向项目的量化分数!");
        }

        // 检查作者列表是否填写
        List<Porprojectauthor> authorList = porprojectauthorService.list(
                Wrappers.lambdaQuery(Porprojectauthor.class)
                        .eq(Porprojectauthor::getPregistrationid, porProjectID)
        );
        if (CollectionUtils.isEmpty(authorList)) {
            throw new BaseException("请先添加纵向项目的作者信息!");
        }

        // 更新状态 - 提交到院级审核
        porProjectRegistration.setProjectState(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK);
        return baseMapper.updateById(porProjectRegistration) == 1;
    }

    /**
     * 纵向项目在研院级审核通过
     * @param token 用户token
     * @param porprojectID 纵向项目编号
     * @return 审核结果
     */
    @Override
    public Boolean collegeCheckPass(String token, String porprojectID) {
        // 1. 查询并校验项目
        Porproject_registration porproject = iPorproject_registrationService.getPorproject(porprojectID);
        if (Objects.isNull(porproject)) {
            throw new BaseException("该纵向项目编号有误!");
        }

        // 2. 校验项目状态 - 院级审核通过需要检查是否处于待院审核状态
        if (!porproject.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该纵向项目状态不处于该环节!");
        }

        // 3. 更新项目状态 - 提交到校级审核
        porproject.setProjectState(StatusCheckConstant.IN_PROGRESS_WAIT_SCHOOL_CHECK);

        // 4. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 构建并保存审核记录
        Audit audit = AuditUtils.buildAudit(
                porprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                "在研待院审核->在研待校审核",
                StatusCheckConstant.PASS
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(porproject) == 1;
    }

    /**
     * 纵向项目在研院级审核打回
     * @param token 用户token
     * @param checkBackDTO 打回参数
     * @return 审核结果
     */
    @Override
    public Boolean collegeCheckBack(String token, CheckBackDTO checkBackDTO) {
        String porprojectID = checkBackDTO.getID();
        // 1. 查询并校验项目
        Porproject_registration porproject = iPorproject_registrationService.getPorproject(porprojectID);
        if (Objects.isNull(porproject)) {
            throw new BaseException("该纵向项目编号有误!");
        }

        // 2. 校验项目状态 - 院级审核退回需要检查是否处于待院审核状态
        if (!porproject.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该纵向项目状态不处于该环节!");
        }

        // 3. 更新状态及原因
        porproject.setProjectState(StatusCheckConstant.IN_PROGRESS_BACK);
        porproject.setReason(checkBackDTO.getReason());

        // 4. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 添加审核记录
        Audit audit = AuditUtils.buildAudit(
                porprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                "在研待院审核->项目在研退回",
                checkBackDTO.getReason()
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(porproject) == 1;
    }

    /**
     * 提交纵向项目结题申请
     * @param porProjectID 纵向项目编号
     * @return 提交成功返回true
     */
    @Override
    public Boolean CommitPorprojectFinish(String porProjectID) {
        //校验参数
        Porproject_registration porProjectRegistration = validatePorProjectRegistration(porProjectID);

        if (!porProjectRegistration.getProjectState().equals(StatusCheckConstant.IN_PROGRESS) && !porProjectRegistration.getProjectState().equals(StatusCheckConstant.DRAFT) && !porProjectRegistration.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_BACK) && !porProjectRegistration.getProjectState().equals(StatusCheckConstant.PROJECT_FINISH_BACK)) {
            throw new BaseException("该纵向项目不适用于该阶段!");
        }

        // 检查量化分数是否填写
        Project_Qualification qualification = iProjectQualificationService.getOne(
                Wrappers.lambdaQuery(Project_Qualification.class)
                        .eq(Project_Qualification::getProjectID, porProjectID)
        );
        if (Objects.isNull(qualification)) {
            throw new BaseException("请先填写纵向项目的量化分数!");
        }

        // 更新状态 - 提交到院级审核
        porProjectRegistration.setProjectState(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK);
        return baseMapper.updateById(porProjectRegistration) == 1;
    }

    /**
     * 纵向项目结题院级审核通过
     * @param token 用户token
     * @param porprojectID 纵向项目编号
     * @return 审核结果
     */
    @Override
    public Boolean collegeFinishCheckPass(String token, String porprojectID) {
        // 1. 查询并校验项目
        Porproject_registration porproject = iPorproject_registrationService.getPorproject(porprojectID);
        if (Objects.isNull(porproject)) {
            throw new BaseException("该纵向项目编号有误!");
        }

        // 2. 校验项目状态 - 院级审核通过需要检查是否处于待院审核状态
        if (!porproject.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该纵向项目状态不处于该环节!");
        }

        // 3. 更新项目状态 - 提交到校级审核
        porproject.setProjectState(StatusCheckConstant.FINISH_WAIT_SCHOOL_CHECK);

        // 4. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 构建并保存审核记录
        Audit audit = AuditUtils.buildAudit(
                porprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                "结题待院审核->结题待校审核",
                StatusCheckConstant.PASS
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(porproject) == 1;
    }

    /**
     * 纵向项目结题院级审核打回
     * @param token 用户token
     * @param checkBackDTO 打回参数
     * @return 审核结果
     */
    @Override
    public Boolean collegeFinishCheckBack(String token, CheckBackDTO checkBackDTO) {
        String porprojectID = checkBackDTO.getID();
        // 1. 查询并校验项目
        Porproject_registration porproject = iPorproject_registrationService.getPorproject(porprojectID);
        if (Objects.isNull(porproject)) {
            throw new BaseException("该纵向项目编号有误!");
        }

        // 2. 校验项目状态 - 院级审核退回需要检查是否处于待院审核状态
        if (!porproject.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该纵向项目状态不处于该环节!");
        }

        // 3. 更新状态及原因
        porproject.setProjectState(StatusCheckConstant.PROJECT_FINISH_BACK);
        porproject.setReason(checkBackDTO.getReason());

        // 4. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 添加审核记录
        Audit audit = AuditUtils.buildAudit(
                porprojectID,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                "结题待院审核->项目结题退回",
                checkBackDTO.getReason()
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(porproject) == 1;
    }

    /**
     * 获取项目
     * @param porProjectPageQuery 查询参数
     * @return 项目列表
     */
    @Override
    public CommonPage<Porproject_registration> userGetProjects(PorProjectPageQuery porProjectPageQuery) {
        String userId = BaseContext.getCurrentId();
        User user = iUserService.getById(userId);

        // 创建MyBatis-Plus的Page对象
        Page<Porproject_registration> page = new Page<>(porProjectPageQuery.getPageNum(), porProjectPageQuery.getPageSize());
        IPage<Porproject_registration> porprojectRegistrationIPage = queryPorProjects(page, porProjectPageQuery, user, false);

        return buildCommonPage(porprojectRegistrationIPage, false);
    }

    /**
     * 纵向项目导出
     *
     * @param porProjectPageQuery 查询条件
     * @return 导出数据
     */
    @Override
    public CommonPage<Porproject_registration> export(PorProjectPageQuery porProjectPageQuery) {
        String userId = BaseContext.getCurrentId();
        User user = iUserService.getById(userId);

        // 创建MyBatis-Plus的Page对象
        Page<Porproject_registration> page = new Page<>(porProjectPageQuery.getPageNum(), porProjectPageQuery.getPageSize());
        IPage<Porproject_registration> porprojectRegistrationIPage = queryPorProjects(page, porProjectPageQuery, user, true);

        return buildCommonPage(porprojectRegistrationIPage, true);
    }

    /**
     * 导出纵向项目
     *
     * @param porProjectExportQuery 查询条件
     * @return 导出的文件
     */
    @Override
    public List<ExportPorProjectVO> exportPorProject(PorProjectExportQuery porProjectExportQuery) {
        String userId = BaseContext.getCurrentId();
        User user = iUserService.getById(userId);
        List<ExportPorProjectVO> exportPorProjectVOList = null;
        //根据角色执行不同查询
        if (user.getRole().equals(RoleConstant.ROLE_ADMIN_SCHOOL)) {
            exportPorProjectVOList = baseMapper.schoolExportPorProject(porProjectExportQuery, user);
        } else if (user.getRole().equals(RoleConstant.ROLE_ADMIN_COLLEGE)) {
            // 院级审核员只能导出自己学院的项目
            exportPorProjectVOList = baseMapper.collegeExportPorProject(porProjectExportQuery, user);
        } else {
            exportPorProjectVOList = baseMapper.userExportPorProject(porProjectExportQuery, user);
        }
        //判空
        if (exportPorProjectVOList == null) {
            return new ArrayList<>();
        }
        //遍历
        for (ExportPorProjectVO exportPorProjectVO : exportPorProjectVOList) {
            exportPorProjectVO.setAccount(iUserService.getById(exportPorProjectVO.getHead()).getAccount());
            List<Porprojectauthor> authors = porprojectauthorService.list(new QueryWrapper<Porprojectauthor>().eq("PRegistrationID", exportPorProjectVO.getPRegistrationID()));
            //将Authors的名字用逗号分隔拼接，并设置
            exportPorProjectVO.setProjectMembers(authors.stream().map(Porprojectauthor::getName).collect(Collectors.joining(",")));
            
            // 将unit字段（DeptID）转换为deptName
            if (exportPorProjectVO.getUnit() != null && !exportPorProjectVO.getUnit().isEmpty()) {
                String deptName = deptMapper.getDeptNameByDeptID(exportPorProjectVO.getUnit());
                if (deptName != null) {
                    exportPorProjectVO.setUnit(deptName);
                }
            }
        }
        return exportPorProjectVOList;
    }
    
    @Override
    public boolean saveDraftProject(PorProjectTSdto porProjectTSdto) {
        // 创建项目实体对象
        Porproject_registration project = new Porproject_registration();
        // 复制属性
        BeanUtil.copyProperties(porProjectTSdto, project);
        
        // 设置录入日期
        if (project.getEnteredDate() == null) {
            project.setEnteredDate(LocalDateTime.now());
        }
        
        // 设置状态为草稿（如果未设置）
        if (project.getProjectState() == null || project.getProjectState().trim().isEmpty()) {
            project.setProjectState("草稿");
        }
        
        // 设置默认值
        if (project.getProjectFlag() == null) {
            project.setProjectFlag(1); // 默认纵向项目
        }
        
        // 处理ID：如果有ID则更新，无ID则新增
        if (project.getPRegistrationID() != null && !project.getPRegistrationID().isEmpty()) {
            // 检查项目是否存在
            Porproject_registration existingProject = this.getById(project.getPRegistrationID());
            if (existingProject != null) {
                // 更新项目
                return this.updateById(project);
            } else {
                // 项目不存在，进行新增
                return this.save(project);
            }
        } else {
            // 使用雪花算法生成ID
            String snowflakeId = String.valueOf(IdWorker.getId());
            // 确保ID长度不超过20字符
            if (snowflakeId.length() > 20) {
                snowflakeId = snowflakeId.substring(0, 20);
            }
            project.setPRegistrationID(snowflakeId);
            // 新增项目
            return this.save(project);
        }
    }


    /**
     * 查询纵向项目
     * @param page 分页对象
     * @param porProjectPageQuery 查询参数
     * @param user 当前用户
     * @param isExport 是否为导出操作
     * @return 查询结果
     */
    private IPage<Porproject_registration> queryPorProjects(Page<Porproject_registration> page,
                                                            PorProjectPageQuery porProjectPageQuery,
                                                            User user,
                                                            boolean isExport) {
        // 根据角色和操作类型执行不同查询
        if (user.getRole().equals(RoleConstant.ROLE_ADMIN_SCHOOL)) {
            // 校级管理员查看所有相关项目
            return isExport ?
                    baseMapper.schoolExportRelatePorprojectQuery(page, porProjectPageQuery, user) :
                    baseMapper.schoolGetRelatePorprojectQuery(page, porProjectPageQuery, user);
        } else if (user.getRole().equals(RoleConstant.ROLE_ADMIN_COLLEGE)) {
            // 院级管理员查看相关项目
            return isExport ?
                    baseMapper.collegeExportRelatePorprojectQuery(page, porProjectPageQuery, user) :
                    baseMapper.collegeGetRelatePorprojectQuery(page, porProjectPageQuery, user);
        } else {
            // 普通用户查看自己相关的项目
            return isExport ?
                    baseMapper.userExportRelatePorprojectQuery(page, porProjectPageQuery, user) :
                    baseMapper.userGetRelatePorprojectQuery(page, porProjectPageQuery, user);
        }
    }

    /**
     * 构建通用分页结果
     * @param porprojectRegistrationIPage 查询结果
     * @param isExport 是否为导出操作
     * @return 通用分页结果
     */
    private CommonPage<Porproject_registration> buildCommonPage(IPage<Porproject_registration> porprojectRegistrationIPage, boolean isExport) {
        // 构造返回分页对象
        CommonPage<Porproject_registration> commonPage = CommonPage.restPage(porprojectRegistrationIPage);
        List<Porproject_registration> records = porprojectRegistrationIPage.getRecords();

        float figure = 0;

        // 遍历记录，转换字段并计算量化分数
        for (Porproject_registration record : records) {
            figure += record.getScore();

            // 如果是导出操作，需要设置额外字段
            if (isExport) {
                record.setAccount(iUserService.getById(record.getHead()).getAccount());
                List<Porprojectauthor> list = porprojectauthorService.query().eq("PRegistrationID", record.getProjectId()).list();
                record.setProjectMembers(list.stream().map(Porprojectauthor::getName).collect(Collectors.joining(",")));
            }
        }

        commonPage.setFigure(figure);
        commonPage.setList(records);

        return commonPage;
    }


    /**
     * 纵向在研校级审核通过
     * @param token 用户token（注：实际未使用，可考虑移除或统一逻辑）
     * @param projectId 纵向项目编号
     * @return 操作结果
     */
    @Override
    public Boolean schoolCheckPass(String token, String projectId) {
        // 1. 查询并校验项目存在性
        Porproject_registration project = iPorproject_registrationService.getPorproject(projectId);
        if (Objects.isNull(project)) {
            throw new BaseException("该纵向项目编号有误!");
        }

        // 2. 校验项目状态 - 校级审核通过需要检查是否处于待校审核状态
        if (!project.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_SCHOOL_CHECK)
                || !project.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该项目状态不处于该环节!");
        }

        // 3. 更新项目状态
        project.setProjectState(StatusCheckConstant.IN_PROGRESS);

        // 4. 获取当前用户信息（使用工具类）
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 构建并保存审核记录（使用工具类）
        Audit audit = AuditUtils.buildAudit(
                projectId,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                project.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_SCHOOL_CHECK) ? "在研待校级审核->项目在研" : "在研待院级审核->在研待校审核",
                StatusCheckConstant.PASS
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(project) == 1;
    }


    /**
     * 纵向在研校级审核打回
     */
    @Override
    public Boolean schoolCheckBack(String token, CheckBackDTO checkBackDTO) {
        String projectId = checkBackDTO.getID();

        // 1. 查询并校验项目存在性
        Porproject_registration project = iPorproject_registrationService.getPorproject(projectId);
        if (Objects.isNull(project)) {
            throw new BaseException("该纵向项目编号有误!");
        }

        // 2. 校验项目状态 - 校级审核退回需要检查是否处于待校审核状态
        if (!project.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_SCHOOL_CHECK)
        || !project.getProjectState().equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)
        || !project.getProjectState().equals(StatusCheckConstant.IN_PROGRESS)) {
            throw new BaseException("该纵向项目状态不处于该环节!");
        }

        // 3. 更新项目状态及退回原因
        project.setProjectState(StatusCheckConstant.IN_PROGRESS_BACK);
        project.setReason(checkBackDTO.getReason());

        // 4. 获取当前用户信息（使用工具类）
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 构建并保存审核记录（使用工具类）
        Audit audit = AuditUtils.buildAudit(
                projectId,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                project.getProjectState() + "->项目在研退回",
                checkBackDTO.getReason()
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(project) == 1;
    }


    /**
     * 纵向项目结题审核通过
     */
    @Override
    public Boolean schoolFinishCheckPass(String token, String projectId) {
        // 1. 查询并校验项目存在性
        Porproject_registration project = iPorproject_registrationService.getPorproject(projectId);
        if (Objects.isNull(project)) {
            throw new BaseException("该项目编号有误!");
        }

        // 2. 校验项目状态 - 校级审核通过需要检查是否处于待校审核状态
        if (!project.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_SCHOOL_CHECK)
        || !project.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK)) {
            throw new BaseException("该作品状态不处于该环节!");
        }

        // 3. 更新项目状态
        project.setProjectState(StatusCheckConstant.PROJECT_FINISH);
        project.setReason(""); // 清空退回原因

        // 4. 获取当前用户信息（使用工具类）
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 构建并保存审核记录（使用工具类）
        Audit audit = AuditUtils.buildAudit(
                projectId,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                project.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_SCHOOL_CHECK) ? "结题待校级审核->项目结题" : "结题待院级审核->结题待校审核",
                StatusCheckConstant.PASS
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(project) == 1;
    }


    /**
     * 纵向校级结题审核打回
     */
    @Override
    public Boolean schoolFinishCheckBack(String token, CheckBackDTO checkBackDTO) {
        String projectId = checkBackDTO.getID();

        // 1. 查询并校验项目存在性
        Porproject_registration project = iPorproject_registrationService.getPorproject(projectId);
        if (Objects.isNull(project)) {
            throw new BaseException("该纵向项目编号有误!");
        }

        // 2. 校验项目状态 - 校级审核退回需要检查是否处于待校审核状态
        if (!project.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_SCHOOL_CHECK)
        || !project.getProjectState().equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK)
        || !project.getProjectState().equals(StatusCheckConstant.PROJECT_FINISH)) {
            throw new BaseException("该纵向项目状态不处于该环节!");
        }

        // 3. 更新项目状态及退回原因
        project.setProjectState(StatusCheckConstant.PROJECT_FINISH_BACK);
        project.setReason(checkBackDTO.getReason());

        // 4. 获取当前用户信息（使用工具类）
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();

        // 5. 构建并保存审核记录（使用工具类）
        Audit audit = AuditUtils.buildAudit(
                projectId,
                currentUser.getRoleName(),
                currentUser.getUserName(),
                project.getProjectState() + ">项目结题退回",
                checkBackDTO.getReason()
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(project) == 1;
    }


    /**
     * 校验纵向项目是否符合业务规则
     *
     * @param  porProjectID 纵向项目ID
     * @return 校验通过返回 true，否则抛出异常
     */
    private Porproject_registration validatePorProjectRegistration(String porProjectID) {
        Porproject_registration porProjectRegistration = super.getOne(Wrappers.lambdaQuery(Porproject_registration.class)
                .eq(Porproject_registration::getPRegistrationID, porProjectID));
        if (Objects.isNull(porProjectRegistration)) {
            throw new BaseException("纵向项目编号有误!");
        }

        Porproject_registrationDTO porProjectRegistrationDTO = BeanUtil.copyProperties(porProjectRegistration, Porproject_registrationDTO.class);

        // 执行DTO校验
        Set<ConstraintViolation<Porproject_registrationDTO>> violations = validator.validate(porProjectRegistrationDTO);

        // 校验失败则抛出异常（仅包含错误信息）
        if (!violations.isEmpty()) {
            String errorMessage = violations.iterator().next().getMessage();
            throw new BaseException(errorMessage);
        }

        return porProjectRegistration;
    }

    /**
     * 设置负责人 UID 和国民经济行业字符串
     * @param porProjectRegistrationDTO 项目注册 DTO
     * @param porProjectRegistration 项目注册实体
     */
    private void setProjectRegistrationFields(Porproject_registrationDTO porProjectRegistrationDTO, Porproject_registration porProjectRegistration) {
        // 将负责人的工号转化为 UID
        String account = porProjectRegistrationDTO.getAccount();
        //工号判空
        if(account == null || account.trim().isEmpty()){
            throw new BaseException("工号不能为空!");
        }
        User userByAccount = iUserService.getUserByAccount(account);
        porProjectRegistration.setHead(userByAccount.getUid());
        porProjectRegistration.setUnit(userByAccount.getDept());

    }

    /**
     * 在研项目撤回
     * @param token 用户token
     * @param porProjectID 纵向项目编号
     * @return 撤回结果
     */
    @Override
    public Boolean withdrawZXProject(String token, String porProjectID) {
        // 1. 查询并校验项目
        Porproject_registration porproject = iPorproject_registrationService.getPorproject(porProjectID);
        if (Objects.isNull(porproject)) {
            throw new BaseException("该纵向项目编号有误!");
        }

        // 2. 校验项目状态 - 只有在研待院审核或者结题待院审核才能撤回
        String projectState = porproject.getProjectState();
        if (!(projectState.equals(StatusCheckConstant.IN_PROGRESS_WAIT_COLLEGE_CHECK)
                || projectState.equals(StatusCheckConstant.FINISH_WAIT_COLLEGE_CHECK))) {
            throw new BaseException("只有在研待院审核和结题待院审核的项目才能撤回!");
        }

        // 3. 获取当前用户信息
        UserInfoUtils.UserInfo currentUser = userInfoUtils.getCurrentUserInfo();
        String roleName = currentUser.getRoleName();

        // 4. 更新项目状态为草稿
        porproject.setProjectState(StatusCheckConstant.DRAFT);

        // 5. 构建并保存审核记录
        Audit audit = AuditUtils.buildAudit(
                porProjectID,
                roleName,
                currentUser.getUserName(),
                porproject.getProjectState() + "->项目撤回",
                "用户撤回申请"
        );
        auditService.addAudit(audit);

        // 6. 保存项目更新并返回结果
        return baseMapper.updateById(porproject) == 1;
    }

}